package procd

import (
	"time"
)

type Runner interface {
	Submit(Task)
}

type DaemonRunner interface {
	// Submit a daemon task
	Submit(t DaemonTask)

	// Terminate all tasks
	Terminate()

	Start()

	// Schedule a fix rated task
	Schedule(t ScheduledTask)
}

type DaemonRunnerImpl struct {
	tasks      []DaemonTask
	scheduler  *TaskList
	terminated bool
}

func NewDaemonRunner() DaemonRunner {
	return &DaemonRunnerImpl{
		tasks:      make([]DaemonTask, 0),
		terminated: false,
		scheduler:  NewTaskList(),
	}
}

func (d *DaemonRunnerImpl) Submit(t DaemonTask) {
	d.tasks = append(d.tasks, t)
}

func (d *DaemonRunnerImpl) Terminate() {
	d.scheduler.Stop()
	for _, t := range d.tasks {
		t.Terminate()
	}
	d.terminated = true
}

func (d *DaemonRunnerImpl) inactiveTasks() []DaemonTask {
	res := make([]DaemonTask, 0)
	for _, t := range d.tasks {
		if !t.IsAlive() {
			res = append(res, t)
		}
	}
	return res
}

func (d *DaemonRunnerImpl) Start() {
	go d.scheduler.Start()
	for {
		if d.terminated {
			break
		}
		for _, inactiveTask := range d.inactiveTasks() {
			go inactiveTask.Run()
		}
		time.Sleep(1 * time.Second)
	}
}

func (d *DaemonRunnerImpl) ScheduleFunc(f func(), interval int64) {
	// TODO: Task list
	d.scheduler.ScheduleFunc(f, interval)
}

func (d *DaemonRunnerImpl) Schedule(t ScheduledTask) {
	// TODO: Task list
	d.scheduler.Schedule(t, t.WaitMillis())
}

func init() {

}

var _ (DaemonRunner) = (*DaemonRunnerImpl)(nil)
var _ (DaemonTask) = (*DaemonCmdTask)(nil)
